/**
 * 给定N个点，首先给定N-1条边，将其连通
 * 然后还有Q条边，对每一条边问MST
 * 因为权值不超过10，因此有其他解法
 * 但显然是LCT动态维护MST的模板题
 * 
 * 用LCT维护路径最大值所在的节点编号
 * 首先对N个点建点，然后对每一条边(u, v, w)建一个点，记作t，然后link(u, t), link(t, v)
 * 对于后续Q条边(u, v, w)，首先查询(u, v)路径上的最大值，如果小于w，则该边对MST无用，忽略；
 * 否则，更新MST。同时找到最大值所在的节点，记作t，cut(u, t), cut(v, t)，注意参数顺序不能错，只有这样才能将t单独切下来。
 * 然后新建一个节点，仍然记作t，然后link(u, t), link(t, v)即可。link的顺序无所谓。
 */
#include <bits/stdc++.h>
#include <bits/extc++.h>
using namespace std;

using llt = long long;
using vi = vector<int>;
using vll = vector<llt>;
using pii = pair<int, int>;
using pll = pair<llt, llt>;
using Real = long double;

vi Value;

struct lct_t{ // link-cut-tree, 1-index, 只能处理路径

using data_type = int;  // 数据类型
using value_type = int; // 维护的信息类型
using lazy_type = int;  // 延迟标记类型

enum {LEFT = 0, RIGHT = 1};

struct node_t{
    int parent;
	int son[2];
	data_type data;   // 点权
	value_type value; // 信息
    int size;         // 伸展树上的size，也是信息之一
	lazy_type lazy;   // 延迟标记
	int flip;      // 翻转标记
};

int N;
vector<node_t> Nodes;
int toUsed;

static value_type mkValue(const data_type & data){
    return data;
}

// 从下往上计算value，用于pushUp,伸展树应保证ls与rs均有意义
value_type _up_(const value_type & ls, const value_type & rs) {
    // return max(ls, rs);
    if(Value[ls] < Value[rs]) return rs;
    return ls;
}

// 根据变动信息delta计算本节点的信息并且打延迟标记，用于pushDown或者modify
// flip其实也是延迟标记的一部分，这里只计算t，跟t的儿子无关
// 要维护t的data、value和lazy、flip
void _dn_(int t, const lazy_type & delta, int flip) {
	auto & n = Nodes[t];
    if(flip){
        swap(n.son[LEFT], n.son[RIGHT]);
        n.flip ^= 1;
    }
    // if(delta){
    //     n.data += delta;
    //     n.value += delta;
    //     n.lazy += delta;
    // }
    return;
}

/// init之后要手工初始化节点并且link
void init(int n){
	// Nodes.assign((N = n) + 1, {0, {0, 0}, data_zero(), value_zero(), 0, lazy_zero(), 0});
    Nodes.clear();
    Nodes.reserve((N = n) + 1);
    toUsed = 0;
	return;
}

int _newNode(const data_type & data){
    memset(Nodes.data()+(++toUsed),0,sizeof(node_t));
    Value[Nodes[toUsed].data = toUsed] = data;
    _pushUp(toUsed);
    return toUsed;
}

// 根据t节点的儿子，计算t节点
void _pushUp(int t) {
	auto & n = Nodes[t];
	n.value = mkValue(n.data);
    n.size = 1;
    int son = n.son[LEFT];
	if(son) {
		n.size += Nodes[son].size;
		n.value = _up_(Nodes[son].value, n.value);
	}
	son = n.son[RIGHT];
	if(son) {
		n.size += Nodes[son].size;
		/// 必须t在左、右儿子在右
		n.value = _up_(n.value, Nodes[son].value);
	}
	return;
}

// 根据t的延迟去计算t的儿子
void _pushDown(int t) {
	auto & n = Nodes[t];
    if(n.lazy == 0 and n.flip == 0) return;
	
	int son;
	auto & lz = n.lazy;
	auto flip = n.flip;
	if(son = Nodes[t].son[LEFT]) _dn_(son, lz, flip);
	if(son = Nodes[t].son[RIGHT]) _dn_(son, lz, flip);

	lz = 0;
	n.flip = 0;
	return;
}

/// 判断t是否为本splay的根
/// 父亲为零（真树根?），父亲的左右儿子不是t
bool _isRoot(int t){
    int p = Nodes[t].parent;
    return 0 == p or (Nodes[p].son[LEFT] != t and Nodes[p].son[RIGHT] != t);
}

//获取排行，不能用于树根
int _getSN(int t){
    return Nodes[Nodes[t].parent].son[RIGHT] == t ? RIGHT : LEFT;
}

inline void _link(int p,int sn,int t){
    Nodes[Nodes[t].parent = p].son[sn] = t;
}

inline void _rotate(int t){
    int p = Nodes[t].parent;//父节点
    int g = Nodes[p].parent;//祖父节点
    int sn = _getSN(t);
    int osn = sn ^ 1;
    //不需要pushDown，在splay中pushDown

    _link(p, sn, Nodes[t].son[osn]);
    Nodes[t].parent = g;
    if(not _isRoot(p)) Nodes[g].son[_getSN(p)] = t;
    _link(t,osn,p);

    _pushUp(p);
	return;
}

//从根开始逐级下放延迟标记
void _maintain(int t){
    if(not _isRoot(t)) _maintain(Nodes[t].parent);
    _pushDown(t);
}

void _splay(int t){
    _maintain(t);
    while(!_isRoot(t)){
        int p = Nodes[t].parent;
        if(!_isRoot(p)) _getSN(t)==_getSN(p)?_rotate(p):_rotate(t);
        _rotate(t);
    }
    _pushUp(t);
}

//从根到x形成一条链，返回需要做虚实变换的最后一个节点
int _access(int x){
    int t = 0;
    for(;x;x=Nodes[t=x].parent){
        _splay(x);
        Nodes[x].son[RIGHT] = t;//将链接上
        _pushUp(x);
    }
    return t;
}

//令x成为原树的根
void _makeRoot(int x){
    _access(x);
    _splay(x);
    _dn_(x, 0, 1);
	return;
}

//获取x所在树的根节点
int _getRoot(int x){
    _access(x);
    _splay(x);
    while( Nodes[x].son[LEFT] ) x = Nodes[x].son[LEFT];
    _splay(x);
    return x;
}
//令child是parent的子节点
void link(int parent,int child){
    _makeRoot(child);
    Nodes[child].parent = parent; // 注意这里不能用 _link
}

//将child从parent树上切下
void cut(int parent,int child){
    _makeRoot(parent);
    _access(child);
    _splay(child);
    Nodes[child].son[LEFT] = Nodes[Nodes[child].son[LEFT]].parent = 0;
    _pushUp(child);
}

bool isConnect(int x,int y){
    return x == y || _getRoot(x) == _getRoot(y);
}

value_type query(int x, int y){
    _makeRoot(x);
	_access(y);
	_splay(y);
	return Nodes[y].value;
}

static const data_type & data_zero(){
    static const data_type DATA_0 = 0;
	return DATA_0;
}

static const value_type & value_zero(){
    static const value_type VALUE_0 = 0;
	return VALUE_0;
}

void disp(ostream & os){
    os << "Forest: \n";
    for(int i=1;i<=toUsed;++i){
        _pushDown(i);
        const auto & n = Nodes[i];
        os << i << ": ";
        os << "parent = " << n.parent << ", son = [" << n.son[LEFT] << ", " << n.son[RIGHT] << "]";
        os << ", data = " << n.data;
        os << endl;
    }
}

};

int const INF = 210;
int N, Q;
lct_t L;
vi Data;

void work(){ 
    cin >> N >> Q;
    L.init(N + N - 1 + Q);
    Value.assign(N + N - 1 + Q + 1, 0);

    for(int i=1;i<=N;++i){
        L._newNode(-1);
    }

    int k = N;
    llt ans = 0;
    for(int a,b,v,i=1;i<N;++i){
        cin >> a >> b >> v;
        auto t = L._newNode(v);

        ans += v;
        L.link(a, t);
        L.link(t, b);
    }

    for(int a,b,v,q=1;q<=Q;++q){
        cin >> a >> b >> v;
        // cout << q << endl;
        // L.disp(cout);

        auto t = L.query(a, b);
        auto tmp = Value[t];

        if(tmp > v){
            ans -= tmp - v;
 
            L.cut(a, t);
            L.cut(b, t);

            t = L._newNode(v);
            
            L.link(a, t);
            L.link(t, b);

        }
        cout << ans << '\n';
    }
	return;
}

int main(){
#ifndef ONLINE_JUDGE
    freopen("z.txt", "r", stdin);
#endif
    ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);	
    int nofkase = 1;
	// cin >> nofkase;
	while(nofkase--) work();
	return 0;
}